package com.zyx.mpdemo.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zyx.mpdemo.helpers.utils.TransactionUtils;
import com.zyx.mpdemo.mapper.UserMapper;
import com.zyx.mpdemo.model.entity.User;
import com.zyx.mpdemo.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author Yaxi.Zhang
 * @since 2022/3/28 17:10
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Resource
    @Qualifier(value = "transactionExecutor")
    private ExecutorService transactionExecutor;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void transAsyncQuery(){
        User user = new User().setName("张三" + DateUtil.now()).setAge(30).setEmail("zs@qq.com");
        baseMapper.insert(user);
        log.info("user to insert: [{}]", user);
        Long id = user.getId();
        // 未提交事务直接异步查询该用户
        transactionExecutor.execute(() -> {
            log.info("async begin to query...");
            User userQuery = getById(id);
            // 事务还未提交，这里查到的为空
            log.info("user in db:[{}]", userQuery);
        });
        // 模拟异常，如果事务失败，不会发起异步任务
        // 仍然打印了 async begin to query...
        int i = 1 / 0;
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException ex) {
            log.error("exception: [{}]", ex.getMessage(), ex);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void transSyncQuery(){
        User user = new User().setName("张三" + DateUtil.now()).setAge(30).setEmail("zs@qq.com");
        baseMapper.insert(user);
        log.info("user to insert: [{}]", user);
        // 未提交事务直接同步查询该用户
        User userDB = getById(user.getId());
        log.info("user in db: [{}]", userDB);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void syncAfterTransQuery(){
        User user = new User().setName("张三" + DateUtil.now()).setAge(30).setEmail("zs@qq.com");
        baseMapper.insert(user);
        log.info("user to insert: [{}]", user);
        Long id = user.getId();
        // 提交事务后再发起异步指令查询该用户
        TransactionUtils.afterCommitAsyncExecute(transactionExecutor, () -> {
            log.info("async begin to query...");
            // 事务已经提交，这里可以查到
            User userQuery = getById(id);
            log.info("user in db:[{}]", userQuery);
        });
        // 模拟异常，如果事务失败，不会发起异步任务
        // 没有打印 async begin to query...
        int i = 1 / 0;
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException ex) {
            log.error("exception: [{}]", ex.getMessage(), ex);
        }
    }


}

